#include "Lemon_Web.h"
#include "Lemon_NFC.h"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>   //  ESP8266WebServer库
#include <String.h>
#include <FS.h>

Lemon_NFC nfc;
unsigned char Buffer[64];// 建立字符数组用于缓存
bool ConnectFlag = false;
File fsUploadFile;              // 建立文件对象用于闪存文件上传
String WIFI_SSID="";
String WIFI_PASSWD="";

/**********对象定义******************/
WiFiClient client;
ESP8266WebServer esp8266_server(80);// 建立ESP8266WebServer对象，对象名称为esp8266_server#include <ESP8266WiFiMulti.h>   //  ESP8266WiFiMulti库
IPAddress apIP(192, 168, 4, 1);//esp8266-AP-IP地址

Lemon_Web::Lemon_Web(){
  
}

/**************************************************************
*  function : wifi连接 
*             从flish读入存入的wifi信息，并尝试连接
**************************************************************/
void Lemon_Web::Wifi_Connect() {
  unsigned char connect_cnt=0;
  WiFi.mode(WIFI_STA);
  Serial.println(WIFI_SSID);
  Serial.println(WIFI_PASSWD);
  WiFi.begin(WIFI_SSID,WIFI_PASSWD);
  // WiFi.setAutoConnect (true);
  // WiFi.setAutoReconnect (true);
  while (true)
  {
    if (WiFi.status() != WL_CONNECTED)
    {
      delay(500);
      connect_cnt++;
      Serial.println("WiFi not Connect");
      if (connect_cnt > 120)
      { // 60秒后如果还是连接不上，就判定为连接超时
        //后续通过指示灯提示配网
        Serial.print("连接超时！请检查网络环境");
        ConnectFlag = false;
        break;
      }
    }
    if (WiFi.status() == WL_CONNECTED)
    {
      ConnectFlag = true;
      Serial.print("连接成功");
      Serial.println(WiFi.localIP());
      nfc.Write_Url(WiFi.localIP());
      break;
    }
  }
}

/*
*  function : 处理客户端请求
*
*/
void Lemon_Web::Website_handle() {
  esp8266_server.handleClient();
}

/*
* function : 网页资源初始化
*/
void Lemon_Web::Website_init() {
  Serial.println("HTTP esp8266_server"); 
  if (ConnectFlag == false) //需要配网，打开配网WIFI
  {
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    if (WiFi.softAP("DNSServer example"))
    {
      Serial.println("开始");
      //输出短地址
      Serial.println(WiFi.softAPIP());
      nfc.Write_Url(WiFi.softAPIP());
      //输出MAC地址
      Serial.println(WiFi.softAPmacAddress().c_str());
    }
    else
    {
      Serial.println("启动失败！");
    }
  }

  //配网放入资源列表，方便dns拦截
  esp8266_server.begin();                                      // 启动网站服务
  esp8266_server.on("/", HTTP_GET, this->Html_Message_Read); // 设置服务器根目录即'/'的函数'handleRoot' 访问根目录即为配网
  esp8266_server.on("/WiFiconfig", HTTP_GET, this->Wifi_Message_Write);
  esp8266_server.on("/WriteToSPIFFS.html", HTTP_POST, this->respondOK, this->Write_data_to_SPIFFS);
  esp8266_server.on("/LED-Control", this->handleLEDControl); // 告知系统如何处理/LED-Control请求    
  esp8266_server.onNotFound(this->Html_ResourceMessage_Read);  // 设置处理404情况的函数'handleNotFound'
  Serial.println("HTTP esp8266_server started"); //  告知用户ESP8266网络服务功能已经启动
}

/*
*
*  function : 从flish读出wifi信息
*
*/
void Lemon_Web::Wifi_Message_Read() {
  if (SPIFFS.begin())
  {
    //检查文件是否存在
    bool existssid = SPIFFS.exists("/wifissid.txt");
    if (existssid) {
      Serial.println("wifissid.txt file exists!");
      File file = SPIFFS.open("/wifissid.txt", "r");
      String ssid = file.readString();
      WIFI_SSID = ssid;
      Serial.println(WIFI_SSID);
      file.close();
    }
    bool existpass = SPIFFS.exists("/wifipassword.txt");
    if (existpass) {
      Serial.println("wifipassword.txt file exists!");
      File file = SPIFFS.open("/wifipassword.txt", "r");
      String password = file.readString();
      WIFI_PASSWD = password;
      Serial.println(WIFI_PASSWD);
      file.close();
    }
  }
}

/**
 *  function : 将客户端提交的WiFi信息写入flish
 * 
 */
void Lemon_Web::Wifi_Message_Write() {
  esp8266_server.send(200, "text/plain", "设置完成");
  Serial.print("请求体参数a的值:");
  Serial.print("请求体第2个参数的值:");
  WIFI_SSID = esp8266_server.arg("ssid");
  WIFI_PASSWD = esp8266_server.arg("password");
  if (SPIFFS.begin())
  { // 启动SPIFFS
    File sdataFile = SPIFFS.open("/wifissid.txt", "w");// 建立File对象用于向SPIFFS中的file对象
    sdataFile.print(esp8266_server.arg("ssid"));       // 向dataFile写入字符串信息
    sdataFile.close();                           // 完成文件写入后关闭文件
    
    File pdataFile = SPIFFS.open("/wifipassword.txt", "w");// 建立File对象用于向SPIFFS中的file对象
    pdataFile.print(esp8266_server.arg("password"));       // 向dataFile写入字符串信息
    pdataFile.close();                           // 完成文件写入后关闭文件
    
    Serial.println(esp8266_server.arg("ssid"));
    Serial.println(esp8266_server.arg("password"));
    Serial.println("Finished Writing data to SPIFFS");
  }
  else
  {
    Serial.println("SPIFFS Failed to Start.");
  }
  Wifi_Connect();
}

/**
 * function : 向浏览器提交请求的网页数据
 * 
 * todo : 此处需要分级判断提交的数据
 */
void Lemon_Web::Html_Message_Read()
{

  if (SPIFFS.begin())
  {
    //检查文件是否存在
    if (SPIFFS.exists("/Lemon_index.html"))
    {
      Serial.println("The file exists!");
      File f = SPIFFS.open("/Lemon_index.html", "r");
      if (!f)
      {
        // 在打开过程中出现问题f就会为空
        Serial.println("Some thing went wrong trying to open the file...");
      }
      else
      {
        int s = f.size();
        Serial.printf("Size=%d\r\n", s);

        //读取index.html的文本内容
        esp8266_server.streamFile(f, "text/html"); // 并且将该文件返回给浏览器
        //关闭文件
        f.close();
      }
    }
    else
    {
      Serial.println("No such file found.");
    }
  }
}

/*
* function : js css png 资源请求处理
*/

void Lemon_Web::Html_ResourceMessage_Read()
{
  // 获取用户请求资源(Request Resource）
  String reqResource = esp8266_server.uri();
  Serial.print("reqResource: ");
  Serial.println(reqResource);
  String contentType;     // 获取文件类型
  String Fileresource;
  // 通过handleFileRead函数处处理用户请求资源

   if (reqResource.endsWith("/Lemon.html")) {                   // 如果访问地址以"/"为结尾
    Fileresource = "/Lemon.html";                  // 则将访问地址修改为/index.html便于SPIFFS访问
    contentType = "text/html";
  }
  else if(reqResource.endsWith("/Lemon_Wificonfig.html")){
    Fileresource = "/Lemon_Wificonfig.html";
    contentType = "text/html";
  }
  else if(reqResource.endsWith("/EasterEgg.html")){
    Fileresource = "/EasterEgg.html";
    contentType = "text/html";
  }
  else if(reqResource.endsWith("/script.js")){
    Fileresource = "/script.js";
    contentType = "application/javascript";
  }
  else if(reqResource.endsWith("/style.css")){
    Fileresource = "/style.css";
    contentType = "text/css";
  }
  else if(reqResource.endsWith("/index.css")){
    Fileresource = "/index.css";
    contentType = "text/css";
  }
  else if(reqResource.endsWith("/input.png")){
    Fileresource = "/input.png";
    contentType = "image/png";
  }
  else if(reqResource.endsWith("/background.png")){
    Fileresource = "/background.png";
    contentType = "image/png";
  }
  
  SPIFFS.begin();
  if (SPIFFS.exists(Fileresource)) {                     // 如果访问的文件可以在SPIFFS中找到
    File file = SPIFFS.open(Fileresource, "r");          // 则尝试打开该文件
    esp8266_server.streamFile(file, contentType);    // 并且将该文件返回给浏览器
    file.close();                                    // 并且关闭文件
  }
  else {
    // 如果在SPIFFS无法找到用户访问的资源，则回复404 (Not Found)
    esp8266_server.send(404, "text/plain", "404 Not Found"); 
  }
}

/*
* function : 处理客户端的404
*/
void Lemon_Web::handleNotFound() {
  esp8266_server.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}



//回复状态码 200 给客户端
void Lemon_Web::respondOK(){
  esp8266_server.send(200, "text/plain", "上传完成等待刷新"); 
}


void Lemon_Web::Write_data_to_SPIFFS()
{
  unsigned int i;
  unsigned int High = 0;
  unsigned int Low = 1;
  unsigned char picData;
  HTTPUpload& upload = esp8266_server.upload();
  if(upload.status == UPLOAD_FILE_START){                     // 如果上传状态为UPLOAD_FILE_START
    String filename = upload.filename;                        // 建立字符串变量用于存放上传文件名
    
    Serial.println(filename);
    if(!filename.startsWith("/")) filename = "/" + filename;  // 为上传文件名前加上"/"
    Serial.println("File Name: " + filename);                 // 通过串口监视器输出上传文件的名称

    fsUploadFile = SPIFFS.open(filename, "w");            // 在SPIFFS中建立文件用于写入用户上传的文件数据
    
  } else if(upload.status == UPLOAD_FILE_WRITE){          // 如果上传状态为UPLOAD_FILE_WRITE     

    if(fsUploadFile)
      fsUploadFile.write(upload.buf, upload.currentSize); // 向SPIFFS文件写入浏览器发来的文件数据
      
  } else if(upload.status == UPLOAD_FILE_END){           // 如果上传状态为UPLOAD_FILE_END 
    if(fsUploadFile) {                                    // 如果文件成功建立
      fsUploadFile.close();                               // 将文件关闭
      Serial.println(upload.totalSize);       // 通过串口监视器输出文件大小
      
      //将取的数据转换为十六进制存储
      File file = SPIFFS.open("/data.txt", "r");
      File hexfile = SPIFFS.open("/hexdata.txt", "w");
      for (i = 0; i < 346; i++)
      {
        size_t num = file.readBytesUntil('\n', Buffer, 65); // 将接收到的信息使用read读取
        for (int j = 0; j < num / 4; j++)
        {
          picData = Stringtohex(Buffer[High]);
          High = High + 4;
          picData <<= 4;
          picData |= Stringtohex(Buffer[Low]);
          Low = Low + 4;
          hexfile.write(picData);
        }
        High = 0;
        Low = 1;
      }
      Serial.println(hexfile.size());
      file.close();
      hexfile.close();
      Reflash=true;
    } else {                                              // 如果文件未能成功建立
      Serial.println("File upload failed");               // 通过串口监视器输出报错信息
      esp8266_server.send(500, "text/plain", "500: couldn't create file"); // 向浏览器发送相应代码500（服务器错误）
    }
  } 
}

unsigned char Lemon_Web::Stringtohex(unsigned char Buffer)
{
    unsigned char switchchar;
    switch (Buffer)
    {
    case '0':
        switchchar=0x00;
        break;
    case '1':
        switchchar=0x01;
        break;
    case '2':
        switchchar=0x02;
        break;
    case '3':
        switchchar=0x03;
        break;
    case '4':
        switchchar=0x04;
        break;
    case '5':
        switchchar=0x05;
        break;
    case '6':
        switchchar=0x06;
        break;
    case '7':
        switchchar=0x07;
        break;
    case '8':
        switchchar=0x08;
        break;
    case '9':
        switchchar=0x09;
        break;
    case 'a':
        switchchar=0x0a;
        break;
    case 'b':
        switchchar=0x0b;
        break;
    case 'c':
        switchchar=0x0c;
        break;
    case 'd':
        switchchar=0x0d;
        break;
    case 'e':
        switchchar=0x0e;
        break;
    case 'f':
        switchchar=0x0f;
        break;
    }
    return switchchar;
}

//改装一下作为资源显示界面
// 处理/LED-Control请求  
void Lemon_Web::handleLEDControl(){
  File dataFile = SPIFFS.open("/hexdata.txt", "r"); 
   Serial.println("led"); 
  //读取文件内容并且通过串口监视器输出文件信息
  for(int i=0; i<dataFile.size(); i++){
    Serial.print(dataFile.read()); 
    if((i%16==0)&&(i!=0)) Serial.print('\n'); 
  }
 
  // //完成文件读取后关闭文件
  dataFile.close();
  esp8266_server.send(200);
}
